import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Fonction {

	public String O() {

		return "public int nbParam=0; " + "public int f(final ArrayList<Integer> x){"
				+ "return 0;}";

	}

	public String I() {

		return "public int nbParam=1; " + "public int f(final ArrayList<Integer> x){"
				+ "return x.get(0);}";

	}

	ArrayList<Integer> x = new ArrayList<Integer>();

	public String S() {
		return "public int nbParam=1; " + "public int f(final ArrayList<Integer> x){"
				+ "return x.get(0)+1;}";

	}

	public String gauche(String fc) {
		String f = fc;
		String result = "";
		// On commence par la modification du nbr de parametres
		Pattern p = Pattern.compile("\\d+");
		Matcher m = p.matcher(f);
		m.find();
		result = result + f.substring(0, m.start());
		f = f.substring(m.end());
		Integer nb = Integer.parseInt(m.group());
		nb++;
		result += nb.toString();
		result += this.decaleDroite(f);
		return result;

	}

	public String droite(String fc) {
		String f = fc;
		String result = "";
		// On commence par la modification du nbr de parametres
		Pattern p = Pattern.compile("\\d+");
		Matcher m = p.matcher(f);
		m.find();
		result = result + f.substring(0, m.start());
		f = f.substring(m.end());
		Integer nb = Integer.parseInt(m.group());
		nb++;
		result += nb.toString();

		result += f;
		return result;

	}

	public String composition(ArrayList<String> fcts) {
		String f = fcts.get(0);
		String result = "";
		Pattern p = Pattern.compile("\\d+");
		Matcher m = p.matcher(f);
		m.find();
		result = result + f.substring(0, m.start());
		result += this.getNbParams(fcts.get(1));
		f = f.substring(m.end());
		p = Pattern.compile("x.get");
		m = p.matcher(f);
		while (m.find()) {
			result = result + f.substring(0, m.start());
			f = f.substring(m.end() + 1);
			Pattern p2 = Pattern.compile("\\d+");
			Matcher c = p2.matcher(f);
			c.find();
			int i = Integer.parseInt(c.group());
			result += this.getInstruction(fcts.get(i + 1));
			f = f.substring(c.end() + 1);

		}
		result += f;
		return result;

	}

	public String recursion(String fc1, String fc2) {
		String result = "public int nbParam=";
		Integer i = Integer.parseInt(this.getNbParams(fc1)) + 1;
		result += i.toString() + "; "
				+ "public int f(final ArrayList<Integer> x){"
				+ "return x.get(0)==0? "
				+ this.getInstruction(this.decaleDroite(fc1)) + " : "
				+ this.secondPartRec(fc2) + ";}";
		return result;

	}

	public String constructionClasse(String name, String fct){
		return "import java.util.ArrayList; "
				+"public class "
				+name
				+"{ "
				+fct
				+"} ";
	}
	
	private String getInstruction(String fct) {

		String f = fct;
		String result = "";
		Pattern p = Pattern.compile("return ");
		Matcher m = p.matcher(f);
		if (m.find())
			result = result + f.substring(m.end());

		return result.substring(0, result.length() - 2);

	}

	private String getNbParams(String fct) {

		String f = fct;
		Pattern p = Pattern.compile("\\d+");
		Matcher m = p.matcher(f);
		m.find();
		return m.group();

	}

	private String decaleDroite(String fc) {
		String f = fc;
		String result = "";
		// On commence par la modification du nbr de parametres
		Pattern p = Pattern.compile("x.get");
		Matcher m = p.matcher(f);
		while (m.find()) {
			result = result + f.substring(0, m.end() + 1);
			f = f.substring(m.end() + 1);
			Pattern p2 = Pattern.compile("\\d+");
			Matcher c = p2.matcher(f);
			c.find();
			Integer i = Integer.parseInt(c.group());
			i++;
			result += i.toString();
			f = f.substring(c.end());

		}
		result += f;
		return result;
	}

	private String secondPartRec(String fc) {
		String coreFc = this.getInstruction(fc);
		String result = "";
		Pattern p = Pattern.compile("x.get");
		Matcher m = p.matcher(coreFc);
		while (m.find()) {

			Pattern p2 = Pattern.compile("\\d+");
			Matcher c = p2.matcher(coreFc);
			c.find();
			Integer i = Integer.parseInt(c.group());
			if (i == 0) {
				result = result + coreFc.substring(0, m.end() + 1);
				result += "0)-1";
				coreFc.substring(c.end() + 1);
			} else if (i == 1) {
				result = result
						+ coreFc.substring(0, m.start())
						+ "f(new ArrayList<Integer>(){{add(x.get(0)-1); addAll(x.subList(1, x.size()));}})";
				coreFc = coreFc.substring(c.end() + 1);

			} else {
				i--;
				result = result + coreFc.substring(0, m.end() + 1);
				result += i.toString();
				coreFc.substring(m.end() + 1);
			}

		}
		result += coreFc;
		return result;

	}

}
